﻿/* Authors: Tyler Wozniak
 *			Andrew Hall
 * A2: Grid Homework
 */

#include <iostream>
#include <string>
#include <time.h>

using namespace std;

#pragma region Pixel Struct
//our pixel structure
struct Pixel{

	enum color { WHITE, GRAY, BLACK };		// Enum for pixel color
	color pxColor;							//need a color instance
	bool isOn;								//pixel boolean - if false, pixel will not draw

	Pixel(){
		pxColor = WHITE;				//constructor default color is white
		isOn = false;					
	}

	//sets colors based on the number sent (white, grey, or black)
	void setColor(int num)
	{
		switch(num)
			{
			case 0:
				pxColor = WHITE; break;
			case 1:
				pxColor = GRAY; break;
			default:
				pxColor = BLACK; break;
			}

	}

	//Uses the += operator add the color of an other pixel to the current pixel
	void Pixel::operator+=(const Pixel inPixel){
		if(pxColor < inPixel.pxColor)
			pxColor = inPixel.pxColor;
		if(!isOn)
			isOn = true;
	}

	//adds adds the color of the pixel sent to the current pixel
	/*
	void add(Pixel inPixel){
		if(pxColor < inPixel.pxColor)
			pxColor = inPixel.pxColor;
		if(!isOn)
			isOn = true;
	}*/

	//sets the pixel color to white
	void reset(){
		pxColor = WHITE;
		isOn = false;
	}

	//prints out the current pixel. If it's white, print the background color (space)
	void print()
	{
		if(isOn){
			if(pxColor == WHITE){
				cout << ' ';
			}
			else if(pxColor == GRAY){
				cout << (char)177;
			}
			else{
				cout << (char)219;
			}
		}
	}
};

#pragma endregion

#pragma region Fields & Prototypes
Pixel** currentImage;		
const int MAX_SIZE = 10;		//max size for the image

//prototypes
Pixel** makeImage(int row, int col);
void addImages(Pixel**& addedImage, int rows, int cols);
void garbageCollect(Pixel** pxArray, int cols);
void printCurrentImage();
void resetCurrentImage();
Pixel** makeSquares(int row, int col);

#pragma endregion

int main(){
	system("Color 1B");		     // Yay for color changing!
	srand((unsigned)time(NULL)); //Random seed, yay!

	currentImage = new Pixel*[MAX_SIZE];	//initialize array of pixels
	for(int i = 0; i < MAX_SIZE; i++)
	{
		currentImage[i] = new Pixel[MAX_SIZE];
	}
	
	/*  
	//UNCOMMENT THIS BLOCK TO TEST makeSquares() 
	Pixel** temp = makeSquares(10,10);
	addImages(temp,10,10);
	printCurrentImage();
	resetCurrentImage();
	system("pause");
	*/

	//program loop. prompts for input, makes the image, garbage collects, and prompts for more input
	char input;
	int counter = 1;
	do{
		system("CLS"); // Clear the console
		if(counter > 1) // This makes it so that once you've determined at least 1 image, the image is always shown statically at the top
			printCurrentImage();

		int row;
		int col;
		string strInput;
		cout << "Image " << counter << endl;

		do{
			cout << "Enter rows: ";	//prompts for input
			getline(cin,strInput);	//gets the input and stores it
			row = atoi(strInput.c_str());	//cast the input to an int
			if(row < 1 || row > MAX_SIZE)	//checks to see if it's in range
				cout << "Error: Please enter a number between 1 and " << MAX_SIZE << endl;
		}while(row < 1 || row > MAX_SIZE); //can't enter a number outside the range

		do{
			cout << "Enter columns: ";
			getline(cin,strInput);
			col = atoi(strInput.c_str());
			if(col < 1 || col > MAX_SIZE)
				cout << "Error: Please enter a number between 1 and " << MAX_SIZE << endl;
		}while(col < 1 || col > MAX_SIZE); //can't enter a number outside the range

		Pixel** newImage = makeImage(row,col);	//makes the pixel image

		addImages(newImage, row, col);	//adds the image to the array

		system("CLS");				//clear the screen
		printCurrentImage();	//prints the current image!

		do{	//what to do next input loop
			cout << "Next [c, r, q]? ";
			getline(cin,strInput);
			input = strInput[0];
			if(input != 'c' && input != 'r' && input != 'q')
					cout << "Error: Please enter c to create a new image, r to reset the image, or q to quit." << endl;
		}while(input != 'c' && input != 'r' && input != 'q');

		if(input == 'r')
			resetCurrentImage();

		counter++;
	}while(input != 'q');

	garbageCollect(currentImage,MAX_SIZE);
	cout << "\nNice images! See you later :)" << endl;
	system("pause");
}

//sets the image and index for it with the given row and column, and returns the resulting, random image
Pixel** makeImage(int row, int col){
	Pixel** tmp = new Pixel*[row];
	for(int i = 0; i < row; i++)
	{
		tmp[i] = new Pixel[col];
		for(int j = 0; j < col; j++)
		{
			int num = rand() % 3;
			tmp[i][j].setColor(num);
		}
	}

	return tmp;
}

//Takes a 2D array of Pixels and adds it to the current image, then gets rid of the old Image
void addImages(Pixel**& addedImage, int rows, int cols){
	
	for(int i = 0; i < rows; i++){
		for(int j = 0; j < cols; j++){
			//cout << i << j << ": " << addedImage[i][j].pxColor;
			//cout << endl;
			currentImage[i][j] += addedImage[i][j];
		}
	}

	garbageCollect(addedImage,rows);	//deletes the array
}

//deletes a 2D pixel array
void garbageCollect(Pixel** pxArray, int rows){
	for(int i = 0; i < rows; i++)
		delete[] pxArray[i];
	delete[] pxArray;
}

//goes through the array of pixels and calls the print function on each cell
void printCurrentImage(){
	for(int i = 0; i < MAX_SIZE && currentImage[i][0].isOn; i++){
		for(int j = 0; j < MAX_SIZE && currentImage[i][j].isOn; j++){
			currentImage[i][j].print();
		}
		cout << endl;
	}
}

//goes through the array of pixels and calls the reset function on each cell
void resetCurrentImage(){
	for(int i = 0; i < MAX_SIZE; i ++){
		for(int j = 0; j < MAX_SIZE; j++){
			currentImage[i][j].reset();
		}
	}
}

//Makes an image of concentric squares, cycling through the different pixel colors
Pixel** makeSquares(int row, int col){
	Pixel** tmp = new Pixel*[row];	//Create a default temp array
	for(int i = 0; i < row; i++){
		tmp[i] = new Pixel[col];
	}
	for(int i = 0; i <= (min(row, col))/2; i++){
		for(int j = i; j < (col - i); j++)
		{
			tmp[i][j].setColor(i % 3);
			tmp[(row - 1) - i][j].setColor(i % 3);
		}
		for(int j = i; j < (row - i); j++)
		{
			tmp[j][i].setColor(i % 3);
			tmp[j][(col - 1) - i].setColor(i % 3);
		}
	}

	/* Old algorithm...didn't work, but was close and I decided a better way to do it
	   But left the code just in case
	for(int i = 0; i < row; i++){
		int maxR;
		int maxC;
		tmp[i] = new Pixel[col];
		for(int j = 0; j < col; j++){

			if(i == 0 || i == row - 1 || j == 0 || j == col - 1)
				tmp[i][j].setColor(2);
			else if (i % 2 || j % 2)
				tmp[i][j].setColor(0);
		}
	}*/

	return tmp;
}